【アップデート】20%のコスト削減と19%のパフォーマンスアップ!!LambdaのランタイムでGraviton2 processorが利用可能になりました
CX事業本部@大阪の岩田です。本日のアップデートにより、LambdaのランタイムでGraviton2 processorが利用可能になりました。
Lambdaの実行基盤で利用されているFirecrackerのロードマップを確認すると、2020年末ごろからArm CPUサポートがShipped
状態になっていたので、LambdaのGraviton2対応がそろそろ来そうかな?と予想していたのですが、満を持してGraviton2対応がGAされました。
https://github.com/firecracker-microvm/firecracker/projects/13
何がうれしいのか
Graviton ProcessorとはAWSがカスタムビルドしたARM ベースのプロセッサーで、ハイパフォーマンスかつ低コストで利用できるのが最大のメリットです。前述のAWSのアナウンスによると、Graviton2 processorベースのLambdaは従来のx86よりも20%低いコストで19%優れたパフォーマンスを発揮するように設計されているとのことです。
今回更新されたLambdaの料金体系から東京リージョンにおけるLambdaの実行時間あたりの料金を比較すると、Graviton2 processorは従来のx86と比較して以下の通り約20%のコストダウンとなります。
アーキテクチャ | 料金 |
---|---|
x86 | GB-秒あたり$0.0000166667 |
Arm(Graviton2 processor) | GB-秒あたり$0.0000133334 |
さらに、単純な実行時間あたりの課金削減に加えて、パフォーマンス向上による実行時間の削減にも期待できます。例えば、これまでx86で100ミリ秒かかっていた処理がGraviton2 processorで80ミリ秒で終わると仮定すると、20ミリ秒分の課金が削減できることになります。
すでにAWSのブログが公開されていますが、こちらのブログの検証パターンではGraviton2 processorにより
- 約30%の高速化
- 約44%のコスト削減
が実現できるようです
すでにEC2やRDSなどのサービスではGraviton Processor/Graviton2 processorを利用するインスタンスタイプが利用可能になっていましたが、今回のアップデートによりLambdaのランタイムでもGraviton2 processorが利用可能になりました。
Graviton2 processorは全てのランタイムで利用できるわけではなく、Amazon Linux2ベースのランタイムでのに利用できます。つまりPython3.7のようなAmazon LinuxベースのランタイムではGraviton2 processorは利用できません。また、すでにEnd of support phase 1を迎えているNode.js10でも同様にGraviton2 processorは利用できません。
具体的には現時点で
- Node.js 12 、 14
- Python 3.8 、 3.9
- Java 8 (
java8.al2
) 、 11 - .NET Core 3.1
- Ruby 2.7
- Custom Runtime(
provided.al2
)
がGraviton2 processorをサポートしています
試しにPython3.7のLambdaのアーキテクチャをarm64に更新してみたところ
Runtime python3.7 does not support the following architectures [arm64]. Please select different architectures from [x86_64, arm64] or select a different runtime.
というエラーが発生し、更新に失敗しました。
やってみる
実際にGraviton2 processorを利用するLambdaの動作を確認してみます
/proc/cpuinfoの確認
試しにLambdaのランタイムにNode.js 14.xを指定し、以下のコードを実行。
const execSync = require('child_process').execSync; exports.handler = async (event) => { const cmd = 'cat /proc/cpuinfo'; const result = execSync(cmd).toString(); console.log("\n"+result); // TODO implement const response = { statusCode: 200, body: JSON.stringify('Hello from Lambda!'), }; return response; };
アーキテクチャに
- x86_64
- arm64
それぞれを指定した場合の出力を比較してみました。なお、Lambdaのメモリ割り当てはデフォルトの128Mとしています。
x86_64の場合の出力はこちら
processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 63 model name : Intel(R) Xeon(R) Processor @ 2.50GHz stepping : 2 microcode : 0x1 cpu MHz : 2500.008 cache size : 36608 KB physical id : 0 siblings : 2 core id : 0 cpu cores : 2 apicid : 0 initial apicid : 0 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm cpuid_fault invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid smap xsaveopt arat md_clear arch_capabilities bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs bogomips : 5000.01 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management: processor : 1 vendor_id : GenuineIntel cpu family : 6 model : 63 model name : Intel(R) Xeon(R) Processor @ 2.50GHz stepping : 2 microcode : 0x1 cpu MHz : 2500.008 cache size : 36608 KB physical id : 0 siblings : 2 core id : 1 cpu cores : 2 apicid : 1 initial apicid : 1 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm cpuid_fault invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid smap xsaveopt arat md_clear arch_capabilities bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs bogomips : 5000.01 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management:
arm64(Graviton2 processorの場合)の出力はこちら
processor : 0 BogoMIPS : 243.75 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp ssbs CPU implementer : 0x41 CPU architecture: 8 CPU variant : 0x3 CPU part : 0xd0c CPU revision : 1 processor : 1 BogoMIPS : 243.75 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp ssbs CPU implementer : 0x41 CPU architecture: 8 CPU variant : 0x3 CPU part : 0xd0c CPU revision : 1
UnixBenchの比較
せっかくなので従来のx86環境とGraviton2環境を比較してみます。CPUのベンチマークといえばUnixBenchが定番ですね。Lambdaのパッケージ形式としてコンテナイメージを選択した場合もGraviton2 processorが利用できるので、UnixBenchが利用できるコンテナイメージを作成してLambda実行環境で動かしてみます。
まずDockerfileです
# x86向けのイメージのベース FROM amazon/aws-lambda-provided:al2.2021.09.13.11 # Graviton2向け向けのイメージのベース # FROM amazon/aws-lambda-provided:al2 RUN yum install -y git gcc make && \ git clone https://github.com/kdlucas/byte-unixbench.git && \ cd byte-unixbench/UnixBench/ && \ make COPY bootstrap /var/runtime/ COPY bootstrap function.sh /var/task/ RUN chmod 755 /var/runtime/bootstrap /var/task/function.sh CMD ["function.handler"] ENV UB_RESULTDIR /tmp ENV UB_TMPDIR /tmp
デプロイするLambdaの設定がx86かarm64(Graviton2 processor)かに応じてFROM
で指定するベースのイメージを切り替えて下さい
Dockerfile内でCOPYしているbootstrapです
#!/bin/sh set -euo pipefail # Initialization - load function handler source $LAMBDA_TASK_ROOT/"$(echo $_HANDLER | cut -d. -f1).sh" # Processing while true do HEADERS="$(mktemp)" # Get an event. The HTTP request will block until one is received EVENT_DATA=$(curl -sS -LD "$HEADERS" -X GET "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next") # Extract request ID by scraping response headers received above REQUEST_ID=$(grep -Fi Lambda-Runtime-Aws-Request-Id "$HEADERS" | tr -d '[:space:]' | cut -d: -f2) # Run the handler function from the script RESPONSE=$($(echo "$_HANDLER" | cut -d. -f2) "$EVENT_DATA") # Send the response curl -X POST "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/$REQUEST_ID/response" -d "$RESPONSE" done
続いてfunction.sh
#!/bin/bash function handler() { cd /var/task/byte-unixbench/UnixBench/ ./Run -i 5 dhrystone whetstone execl pipe spawn }
こちらがLambdaのハンドラーから呼び出されることになります。テスト実行対象として
- dhrystone
- whetstone
- execl
- pipe
- spawn
を指定しつつ、Lambdaの実行時間上限である15分以内に処理が完了するようにテスト回数を5に減らしています
あとはx86環境用とarm環境用それぞれのコンテナイメージをビルドしてECRにプッシュします
docker build -t cm-iwata/lambda-unixbench:x86_64 . docker tag cm-iwata/lambda-unixbench:x86_64 <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/lambda-unixbench:x86_64 aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com docker push <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/lambda-unixbench:x86_64
プッシュできたら作成したコンテナイメージを参照するようにLambda関数を作成し、以下の設定を編集します
- メモリ(MB)...1792MB
- Lambdaはメモリ割当1.8Gから1vCpu分のフルパワーが利用できるようになります
- タイムアウト...15分
設定できたらテスト実行してUnixBenchの出力を確認しましょう。結果は以下の通りでした
結果(x86_64)
make all make[1]: Entering directory `/var/task/byte-unixbench/UnixBench' make distr make[2]: Entering directory `/var/task/byte-unixbench/UnixBench' Checking distribution of files ./pgms exists ./src exists ./testdir exists ./tmp exists ./results exists make[2]: Leaving directory `/var/task/byte-unixbench/UnixBench' make programs make[2]: Entering directory `/var/task/byte-unixbench/UnixBench' make[2]: Nothing to be done for `programs'. make[2]: Leaving directory `/var/task/byte-unixbench/UnixBench' make[1]: Leaving directory `/var/task/byte-unixbench/UnixBench' # # # # # # # ##### ###### # # #### # # # # ## # # # # # # # ## # # # # # # # # # # # ## ##### ##### # # # # ###### # # # # # # ## # # # # # # # # # # # # ## # # # # # # # ## # # # # #### # # # # # ##### ###### # # #### # # Version 5.1.3 Based on the Byte Magazine Unix Benchmark Multi-CPU version Version 5 revisions by Ian Smith, Sunnyvale, CA, USA January 13, 2011 johantheghost at yahoo period com ------------------------------------------------------------------------------ Use directories for: * File I/O tests (named fs***) = /tmp * Results = /tmp ------------------------------------------------------------------------------ 1 x Dhrystone 2 using register variables 1 2 3 4 5 1 x Double-Precision Whetstone 1 2 3 4 5 1 x Execl Throughput 1 2 1 x Pipe Throughput 1 2 3 4 5 1 x Process Creation 1 2 2 x Dhrystone 2 using register variables 1 2 3 4 5 2 x Double-Precision Whetstone 1 2 3 4 5 2 x Execl Throughput 1 2 2 x Pipe Throughput 1 2 3 4 5 2 x Process Creation 1 2 ======================================================================== BYTE UNIX Benchmarks (Version 5.1.3) System: : GNU/Linux OS: GNU/Linux -- 4.14.243-194.434.amzn2.x86_64 -- #1 SMP Tue Aug 17 23:23:16 UTC 2021 Machine: x86_64 (x86_64) Language: en_US.utf8 (charmap=\"UTF-8\", collate=\"UTF-8\") CPU 0: Intel(R) Xeon(R) Processor @ 2.50GHz (5000.0 bogomips) Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET CPU 1: Intel(R) Xeon(R) Processor @ 2.50GHz (5000.0 bogomips) Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET ; runlevel ------------------------------------------------------------------------ Benchmark Run: Thu Sep 30 2021 07:41:48 - 07:47:28 2 CPUs in system; running 1 parallel copy of tests Dhrystone 2 using register variables 37534408.4 lps (10.0 s, 4 samples) Double-Precision Whetstone 4859.5 MWIPS (9.9 s, 4 samples) Execl Throughput 3928.1 lps (29.9 s, 2 samples) Pipe Throughput 1517401.9 lps (10.0 s, 4 samples) Process Creation 7633.7 lps (30.0 s, 2 samples) System Benchmarks Partial Index BASELINE RESULT INDEX Dhrystone 2 using register variables 116700.0 37534408.4 3216.3 Double-Precision Whetstone 55.0 4859.5 883.5 Execl Throughput 43.0 3928.1 913.5 Pipe Throughput 12440.0 1517401.9 1219.8 Process Creation 126.0 7633.7 605.8 ======== System Benchmarks Index Score (Partial Only) 1139.2 ------------------------------------------------------------------------ Benchmark Run: Thu Sep 30 2021 07:47:28 - 07:53:05 2 CPUs in system; running 2 parallel copies of tests Dhrystone 2 using register variables 37851790.7 lps (10.0 s, 4 samples) Double-Precision Whetstone 5320.4 MWIPS (9.2 s, 4 samples) Execl Throughput 3462.3 lps (29.5 s, 2 samples) Pipe Throughput 1537607.3 lps (10.0 s, 4 samples) Process Creation 8282.3 lps (30.0 s, 2 samples) System Benchmarks Partial Index BASELINE RESULT INDEX Dhrystone 2 using register variables 116700.0 37851790.7 3243.5 Double-Precision Whetstone 55.0 5320.4 967.3 Execl Throughput 43.0 3462.3 805.2 Pipe Throughput 12440.0 1537607.3 1236.0 Process Creation 126.0 8282.3 657.3 ======== System Benchmarks Index Score (Partial Only) 1154.7
結果(arm64)
make all make[1]: Entering directory `/var/task/byte-unixbench/UnixBench' make distr make[2]: Entering directory `/var/task/byte-unixbench/UnixBench' Checking distribution of files ./pgms exists ./src exists ./testdir exists ./tmp exists ./results exists make[2]: Leaving directory `/var/task/byte-unixbench/UnixBench' make programs make[2]: Entering directory `/var/task/byte-unixbench/UnixBench' make[2]: Nothing to be done for `programs'. make[2]: Leaving directory `/var/task/byte-unixbench/UnixBench' make[1]: Leaving directory `/var/task/byte-unixbench/UnixBench' # # # # # # # ##### ###### # # #### # # # # ## # # # # # # # ## # # # # # # # # # # # ## ##### ##### # # # # ###### # # # # # # ## # # # # # # # # # # # # ## # # # # # # # ## # # # # #### # # # # # ##### ###### # # #### # # Version 5.1.3 Based on the Byte Magazine Unix Benchmark Multi-CPU version Version 5 revisions by Ian Smith, Sunnyvale, CA, USA January 13, 2011 johantheghost at yahoo period com ------------------------------------------------------------------------------ Use directories for: * File I/O tests (named fs***) = /tmp * Results = /tmp ------------------------------------------------------------------------------ 1 x Dhrystone 2 using register variables 1 2 3 4 5 1 x Double-Precision Whetstone 1 2 3 4 5 1 x Execl Throughput 1 2 1 x Pipe Throughput 1 2 3 4 5 1 x Process Creation 1 2 2 x Dhrystone 2 using register variables 1 2 3 4 5 2 x Double-Precision Whetstone 1 2 3 4 5 2 x Execl Throughput 1 2 2 x Pipe Throughput 1 2 3 4 5 2 x Process Creation 1 2 ======================================================================== BYTE UNIX Benchmarks (Version 5.1.3) System: : GNU/Linux OS: GNU/Linux -- 4.14.243-194.434.amzn2.aarch64 -- #1 SMP Tue Aug 17 23:22:56 UTC 2021 Machine: aarch64 (aarch64) Language: en_US.utf8 (charmap=\"UTF-8\", collate=\"UTF-8\") ; runlevel ------------------------------------------------------------------------ Benchmark Run: Thu Sep 30 2021 06:40:31 - 06:46:08 2 CPUs in system; running 1 parallel copy of tests Dhrystone 2 using register variables 41879150.0 lps (10.0 s, 4 samples) Double-Precision Whetstone 5925.2 MWIPS (9.7 s, 4 samples) Execl Throughput 5401.7 lps (30.0 s, 2 samples) Pipe Throughput 1721879.1 lps (10.0 s, 4 samples) Process Creation 9100.0 lps (30.0 s, 2 samples) System Benchmarks Partial Index BASELINE RESULT INDEX Dhrystone 2 using register variables 116700.0 41879150.0 3588.6 Double-Precision Whetstone 55.0 5925.2 1077.3 Execl Throughput 43.0 5401.7 1256.2 Pipe Throughput 12440.0 1721879.1 1384.1 Process Creation 126.0 9100.0 722.2 ======== System Benchmarks Index Score (Partial Only) 1371.6 ------------------------------------------------------------------------ Benchmark Run: Thu Sep 30 2021 06:46:08 - 06:51:51 2 CPUs in system; running 2 parallel copies of tests Dhrystone 2 using register variables 42419526.5 lps (10.0 s, 4 samples) Double-Precision Whetstone 6027.4 MWIPS (9.6 s, 4 samples) Execl Throughput 4147.8 lps (29.6 s, 2 samples) Pipe Throughput 1716980.9 lps (10.0 s, 4 samples) Process Creation 8764.6 lps (30.0 s, 2 samples) System Benchmarks Partial Index BASELINE RESULT INDEX Dhrystone 2 using register variables 116700.0 42419526.5 3634.9 Double-Precision Whetstone 55.0 6027.4 1095.9 Execl Throughput 43.0 4147.8 964.6 Pipe Throughput 12440.0 1716980.9 1380.2 Process Creation 126.0 8764.6 695.6 ======== System Benchmarks Index Score (Partial Only) 1298.3
今回はメモリの割当を1792MBで実行しているので、1並列でテストを実行した結果で比較するのが良さそうですね。スコアとしては
- x86...1139.2
- arm64(Graviton2)...1371.6
という結果でした。Lambda実行環境のデプロイ先としてどのハードウェアを引き当てるかというガチャ要素があるため、本来はもう少しテスト回数を重ねたいところではありますが、概ねカタログスペックである19%近くスコアがアップしていることが確認できました。
まとめ
Lambdaをバリバリ活用されているシステムでは
- 処理の高速化
- コスト削減
ともに期待できる非常にうれしいアップデートではないでしょうか?
既存のコードがそのまま正しく動作するかの検証は必要ですが、もしGraviton2 processorに移行できれば大きなメリットが享受できそうです。既存のワークロードをGraviton2 processorに移行できないか、是非一度検証してみて下さい。